﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace LaoLuo.Web
{
    /// <summary>
    /// 
    /// </summary>
    public class CaptchaProvider
    {
        private readonly Random _rnd = new Random();
        private readonly int _imgWidth;
        private readonly int _imgHeight;
        private readonly float _fontSize;

        private readonly HashSet<string> _fontFamilies = new HashSet<string>
            {
                "Comic Sans MS",
                "Arial",
                "Times New Roman",
                "Georgia",
                "Verdana",
                "Geneva"
            };

        /*private readonly Brush[] _brusheses = new[]
            {
                //Brushes.Black,
                Brushes.DarkGray,
                Brushes.Silver,
                Brushes.DarkKhaki,
                Brushes.Brown,
                Brushes.PaleVioletRed
            };*/

        private readonly HashSet<HatchStyle> _hatchStyles = new HashSet<HatchStyle>
            {
                HatchStyle.BackwardDiagonal,
                HatchStyle.Cross,
                HatchStyle.DashedDownwardDiagonal,
                HatchStyle.DashedHorizontal,
                HatchStyle.DashedUpwardDiagonal,
                HatchStyle.DashedVertical,
                HatchStyle.DiagonalBrick,
                HatchStyle.DiagonalCross,
                HatchStyle.Divot,
                HatchStyle.DottedDiamond,
                HatchStyle.DottedGrid,
                HatchStyle.ForwardDiagonal,
                HatchStyle.Horizontal,
                HatchStyle.HorizontalBrick,
                HatchStyle.LargeCheckerBoard,
                HatchStyle.LargeConfetti,
                HatchStyle.LargeGrid,
                HatchStyle.LightDownwardDiagonal,
                HatchStyle.LightHorizontal,
                HatchStyle.LightUpwardDiagonal,
                HatchStyle.LightVertical,
                HatchStyle.Max,
                HatchStyle.Min,
                HatchStyle.NarrowHorizontal,
                HatchStyle.NarrowVertical,
                HatchStyle.OutlinedDiamond,
                HatchStyle.Shingle,
                HatchStyle.SmallConfetti,
                HatchStyle.SolidDiamond,
                HatchStyle.Sphere,
                HatchStyle.Trellis,
                HatchStyle.Vertical,
                HatchStyle.Wave,
                HatchStyle.Weave,
                HatchStyle.WideDownwardDiagonal,
                HatchStyle.WideUpwardDiagonal,
                HatchStyle.ZigZag
            };

        private readonly HashSet<FontStyle> _fontStyles = new HashSet<FontStyle>
            {
                FontStyle.Bold,
                FontStyle.Italic,
                FontStyle.Regular
            };

        /// <summary>
        /// 
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="fontSize"> </param>
        public CaptchaProvider(int width = 65, int height = 20, int fontSize = 12)
        {
            _imgWidth = width;
            _imgHeight = height;
            _fontSize = fontSize;
        }

        /// <summary>
        /// 
        /// </summary>
        public ICollection<FontStyle> FontStyles
        {
            get { return _fontStyles; }
        }

        /// <summary>
        /// 
        /// </summary>
        public ICollection<string> FontFamilies
        {
            get { return _fontFamilies; }
        }

        /// <summary>
        /// 
        /// </summary>
        public ICollection<HatchStyle> HatchStyles
        {
            get { return _hatchStyles; }
        }

        /*/// <summary>
        /// 
        /// </summary>
        public FontStyle[] FontStyles
        {
            get { return _fontStyles; }
            set { _fontStyles = value; }
        }*/

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Bitmap GetImage(string code)
        {
            var bitmap = new Bitmap(_imgWidth, _imgHeight);
            DrawNoise(bitmap);
            DrawCode(bitmap, code);
            return bitmap;
        }

        private void DrawNoise(Image image)
        {
            var g = Graphics.FromImage(image);

            var brush = new HatchBrush(_hatchStyles.RandomSingle(),
                                       Color.FromArgb((RandomProvider.RandomNumber.Next(100, 255)),
                                                      (RandomProvider.RandomNumber.Next(100, 255)),
                                                      (RandomProvider.RandomNumber.Next(100, 255))),
                                       Color.White);

            g.FillRectangle(brush, new RectangleF(0, 0, image.Width, image.Height));
        }

        private void DrawCode(Image image, string code)
        {
            var oGraphics = Graphics.FromImage(image);

            /*var font = new Font(_fontFamily[RandomProvider.RandomNumber.Next(_fontFamily.Length - 1)], _fontSize, FontStyle.Bold);

            g.DrawString(validateCode, font, _brusheses[RandomProvider.RandomNumber.Next(_brusheses.Length - 1)], RandomProvider.RandomNumber.Next(-3, 11), RandomProvider.RandomNumber.Next(-4, 1));

            g.DrawString()*/

            var oMatrix = new Matrix();
            var y = _imgHeight / 2.5f;
            for (var i = 0; i <= code.Length - 1; i++)
            {
                oMatrix.Reset();
                var x = _imgWidth / code.Length * i /*+ ((float)_imgWidth / code.Length) / 2f*/;

                //Rotate text Random
                oMatrix.RotateAt(_rnd.Next(-15, 15), new PointF(x, y));
                oGraphics.Transform = oMatrix;

                //Draw the letters with Random Font Type, Size and Color
                oGraphics.DrawString
                    (
                    //Text
                    code.Substring(i, 1),
                    //Random Font Name and Style
                    new Font(_fontFamilies.RandomSingle(),
                             _fontSize,
                             _fontStyles.RandomSingle()),
                    //Random Color (Darker colors RGB 0 to 100)
                    new SolidBrush(
                        Color.FromArgb(RandomProvider.RandomNumber.Next(0, 100),
                                       RandomProvider.RandomNumber.Next(0, 100),
                                       RandomProvider.RandomNumber.Next(0, 100))),
                    x,
                    y
                    );

                oGraphics.ResetTransform();
            }
        }
    }
}